﻿using NewLife.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace GXRTBTC.PublicClassLibrary.Util
{
    public static class TcsTimeoutHelper
    {
        /// <summary>
        /// 等待TaskCompletionSource的结果，并设置超时时间
        /// </summary>
        /// <typeparam name="T">结果类型</typeparam>
        /// <param name="tcs">TaskCompletionSource实例</param>
        /// <param name="timeout">超时时间</param>
        /// <returns>返回业务结果或抛出超时异常</returns>
        /// <exception cref="TimeoutException"></exception>
        public static async Task<T> WaitWithTimeout<T>(TaskCompletionSource<T> tcs, TimeSpan timeout)
        {
            // 创建超时任务（延迟指定时间后完成）
            Task delayTask = Task.Delay(timeout);

            //同时等待业务任务和超时任务，哪个先完成就执行哪个
            Task completedTask = await Task.WhenAny(tcs.Task, delayTask);

            // 如果先完成的是超时任务，则抛出超时异常
            if (completedTask == delayTask)
            {
                // 可选：标记TaskCompletionSource为取消状态（根据业务需求）
                tcs.TrySetCanceled();
                throw new TimeoutException($"等待超时（超过{timeout.TotalMilliseconds}毫秒）");
            }

            // 业务任务先完成，返回结果（若任务异常，会在此处抛出）
            return await tcs.Task;
        }

        /// <summary>
        /// 任务控制器管理
        /// </summary>
        public static TcsManager tcsManager { get; set; } = new();
    }

    /// <summary>
    /// 任务控制器管理
    /// </summary>
    public class TcsManager
    {
        /// <summary>
        /// 任务控制器集合
        /// </summary>
        private Dictionary<string, TaskCompletionSource<Object>> _reqTcss { get; set; } = new();
        private Dictionary<string, DateTime> _tcsTimes { get; set; } = new();
        /// <summary>
        /// 过期删除时间
        /// </summary>
        public int timeOutSeconds { get; set; } = 20;
        /// <summary>
        /// 构造
        /// </summary>
        public TcsManager()
        {
            new Thread(TimerClear).Start();
        }
        /// <summary>
        /// 过期定时清除
        /// </summary>
        private void TimerClear()
        {
            while (true)
            {
                try
                {
                    List<string> tcsKeys = _tcsTimes.Keys.ToList();
                    foreach (string tcsKey in tcsKeys)
                    {
                        if ((DateTime.Now - _tcsTimes[tcsKey]).TotalSeconds > timeOutSeconds)
                        {
                            _reqTcss.Remove(tcsKey);
                            _tcsTimes.Remove(tcsKey);
                        }
                    }
                }
                catch { }
                finally
                {
                    Thread.Sleep(5 * 1000);
                }
            }
        }
        /// <summary>
        /// 设置任务控制器
        /// </summary>
        /// <param name="key"></param>
        public TaskCompletionSource<Object> SetTcs(string tcsKey)
        {
            _reqTcss.TryAdd(tcsKey, new TaskCompletionSource<Object>());
            _tcsTimes.TryAdd(tcsKey, DateTime.Now);
            return _reqTcss[tcsKey];
        }
        /// <summary>
        /// 获取任务控制器
        /// </summary>
        /// <param name="key"></param>
        public TaskCompletionSource<Object> GetTcs(string tcsKey)
        {
            if (_reqTcss.ContainsKey(tcsKey))
            { 
                return _reqTcss[tcsKey];
            }

            return null;
        }
        public void RemoveTcs(string tcsKey)
        {
            if (_reqTcss.ContainsKey(tcsKey))
            {
                _reqTcss.Remove(tcsKey);
            }
        }
    }
}
